package com.sse.service.impl;

import com.sse.context.SseSessionHolder;
import com.sse.exception.SseException;
import com.sse.service.SseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;


/**
 * SSE 相关业务实现
 */
@Service
public class SseServiceImpl implements SseService {

    private static final Logger logger = LoggerFactory.getLogger(SseServiceImpl.class);

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 新建连接
     *
     * @param clientId 客户端ID
     */
    @Override
    public SseEmitter start(String clientId) {
        // 默认180秒超时,设置为0L则永不超时,可以调整
        long timeout = 180_000L;
        SseEmitter emitter = new SseEmitter(timeout);
        logger.info("MSG: Sse连接成功 | ID: {} | Date: {}", clientId, LocalDateTime.now());
        SseSessionHolder.add(clientId, emitter);

        emitter.onCompletion(() ->
                SseSessionHolder.onCompletion(
                        clientId,
                        () -> logger.info("MSG: Sse连接结束 | ID: {} | Date: {}", clientId, LocalDateTime.now())
                )
        );

        emitter.onTimeout(() -> {
            logger.warn("MSG: Sse连接超时 | ID: {} | Date: {}", clientId, LocalDateTime.now());
            SseSessionHolder.onError(clientId, new SseException("TimeOut(clientId: " + clientId + ")"));
        });

        emitter.onError(t -> {
            logger.error("MSG: Sse连接出错 | ID: {} | Date: {}", clientId, LocalDateTime.now());
            SseSessionHolder.onError(clientId, new SseException("Error(clientId: " + clientId + ")"));
        });

        String prefix = "SSE:userId_";
        redisTemplate.opsForValue().set(prefix + clientId, emitter, timeout, TimeUnit.MILLISECONDS);
        return emitter;
    }

    /**
     * 发送数据
     *
     * @param clientId 客户端ID
     */
    @Override
    public String send(String clientId) {
        if (SseSessionHolder.send(clientId, System.currentTimeMillis())) {
            return "Succeed!";
        }
        return "error";

    }

    /**
     * 关闭连接
     *
     * @param clientId 客户端ID
     */
    @Override
    public String close(String clientId) {
        if (SseSessionHolder.delete(clientId)) {
            logger.info("MSG: Sse关闭成功 | ID: {} | Date: {}", clientId, LocalDateTime.now());
            return "Succeed!";
        }
        return "Error!";
    }
}
